﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;

namespace Nethouse.Lib.EventBus
{
    public class EventBus : IEventBus
    {
        private readonly Dictionary<Type, List<Action<object>>> handlers = new Dictionary<Type, List<Action<object>>>();

        public void Subscribe<T>(Action<T> handler)
        {
            if (!handlers.ContainsKey(typeof (T)))
            {
                handlers.Add(typeof (T), new List<Action<object>>());
            }
            handlers[typeof (T)].Add(e => handler((T) e));
        }

        public void Publish<T>(T e)
        {
            var eventType = typeof (T);
            foreach (Type handlerType in handlers.Keys)
            {
                TryPublishForType(handlerType, eventType, e);
            }
        }

        private void TryPublishForType(Type handlerType, Type eventType, object e)
        {
            if (handlerType.IsAssignableFrom(eventType))
            {
                handlers[handlerType].ForEach(handler => handler(e));
            }
        }

        private static readonly IEventBus staticEventBus = new EventBus();

        public static IEventBus GetRequestHostedEventBus()
        {
            return HttpContext.Current != null ? GetHttpRequestEventBus() : staticEventBus;
        }

        private const string EventBusId = "Lib.EventBus";

        private static IEventBus GetHttpRequestEventBus()
        {
            var eventBus = HttpContext.Current.Items[EventBusId] as IEventBus;

            if (eventBus == null)
            {
                eventBus = new EventBus();
                HttpContext.Current.Items[EventBusId] = eventBus;
            }
            return eventBus;
        }
    }

}